package com.woniu51.order.service.impl;

import com.woniu.cinema.api.CinemaFeignClient;
import com.woniu.cinema.vo.HallMovieVo;
import com.woniu.common.core.text.Convert;
import com.woniu.common.enums.ExceptionCode;
import com.woniu.common.exception.CustomException;
import com.woniu51.order.config.RabbitMqConfig;
import com.woniu51.order.domain.Order;
import com.woniu51.order.domain.OrderSeat;
import com.woniu51.order.dto.OrderDto;
import com.woniu51.order.mapper.OrderMapper;
import com.woniu51.order.mapper.OrderSeatMapper;
import com.woniu51.order.service.OrderService;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * @author 杨光
 * @date 2022年04月08日 16:02
 */
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private CinemaFeignClient cinemaFeignClient;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderSeatMapper orderSeatMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    //检查某一个场次的票是否足够
    public void checkTicketCountEnough(OrderDto orderDto){
        //定义一个LUA脚本
        //因为LUA脚本在redis中可以保证多个语句作为一个原子操作被执行
        /*
        String luaScript = "" +
                "local availableTicket = redis.call('get',KEYS[1]); " +   //从redis中根据key获取一个value
                "if (availableTicket==false) then return 0; end;" +
                "if 144 >= 2" +
                "  then redis.call('decrby',KEYS[1],2);" +
                "  return 1; " +
                "else return 0; " +
                "end";

        DefaultRedisScript<Long> script = new DefaultRedisScript(luaScript,Long.class);

        Object result = redisTemplate.execute(script, Arrays.asList("redis_key_cache_seat_count_" + orderDto.getHallMovieId()),
                orderDto.getSeatIdList().size());
        //预减库存
        if(((Long)result)==0L){
            throw new CustomException(ExceptionCode.NOT_ENOUGH_TICKET);
        }*/
    }

    @Override
    public Order queryByOrderId(Long oid) {

        return orderMapper.selectByPrimaryKey(oid);

    }

    @Override
    public Integer confirmPay(Long oid) {


        return orderMapper.confirmPay(oid);
    }

    @Override
    @Transactional
    @GlobalTransactional //开启seata的全局事务
    public void makeOrder(OrderDto orderDto) {



        //1.添加记录到订单表
        Order order = new Order();
        //1.1调用cinema service微服务 ，根据hallMovieId查询票价
        HallMovieVo hallMovieVo = cinemaFeignClient.queryHallMovieById4Feign(orderDto.getHallMovieId());
        List<Integer> seatIdList = orderDto.getSeatIdList();
        Long orderId = Convert.toLong(orderDto.getOrderIdStr().substring(1));
        order.setOrderId(orderId);
        order.setUserId(orderDto.getUserId());
        order.setOrderTotalDiscount(0);
        order.setOrderCount(seatIdList.size());
        order.setOrderTotal(seatIdList.size()*hallMovieVo.getFareMoney());
        order.setOrderTotalPay(seatIdList.size()*hallMovieVo.getFareMoney());
        order.setOrderStatus(1);
        order.setFareMoney(hallMovieVo.getFareMoney());
        order.setOrderTime(new Date());
        order.setCinemaId(orderDto.getCinemaId());
        order.setMovieId(orderDto.getMovieId());
        orderMapper.insertSelective(order);

        //2.添加记录到订单详情表
        for (Integer seatId : seatIdList) {
            OrderSeat orderSeat = new OrderSeat();
            orderSeat.setOrderId(orderId);
            orderSeat.setSeatId(seatId);
            orderSeatMapper.insertSelective(orderSeat);
        }


        //3.远程调用cinema service微服务，更新tb_seat表
        Integer result  = cinemaFeignClient.batchUpdateSeatStatus(seatIdList);
        if(result!=seatIdList.size()){

            throw new CustomException(ExceptionCode.SEAT_ALREADY_SOLD);
        }
        //4.发一条消息到rabbitmq，把订单号发过去，如果15分钟不付款，自动取消订单
        rabbitTemplate.convertAndSend(RabbitMqConfig.DELAY_EXCHANGE,RabbitMqConfig.DELAY_ROUTING_KEY,orderId);


    }
}
